<?php
class Coberturas extends MY_Controller {
	/* La cobertura hace referencia en este caso a la realización de las prestaciones pendientes según
	el plan de un afiliado particular */
	// Datos para pasar a las vistas
	var $pageTitle = 'Prevet :: Registrar prestaciones';
	var $nombre_entidad = 'Cobertura';		// Cadena utilizada para los títulos de las páginas

	// Vistas manejadas por el controlador
	var $CARPETA_VISTAS = 'prestaciones/'; 	// Directorio donde están contenidas las vistas gestionadas por el controlador
	var $pagina_editar; 					// Nombre de la vista de edición
	var $pagina_ver_todos;					// Nombre de la vista para mostrar todos
	var $pagina_ver;
	var $pagina_reporte;

	public function __construct()
    {
    	parent::__construct();

    	$this->pagina_editar = $this->CARPETA_VISTAS . 'cobertura_edit_view';
    	$this->pagina_ver_todos = $this->CARPETA_VISTAS . 'cobertura_ver_todos_view';
    	$this->pagina_ver = $this->CARPETA_VISTAS . 'cobertura_ver_view';
    	$this->pagina_reporte .= 'reportes/cobertura_report_view';
	}
	
	public function nueva($id_afiliado)
	{
		# Para el afiliado indicado, debo buscar cuál es el plan actual y a ése, asociarle la nueva prestación realizada
		$this->load->library('util_historial_plan');
		$id_hist_plan = $this->util_historial_plan->getIdHistorialPlanActual($id_afiliado);

		$this->registrar($id_hist_plan);
	}

	public function registrar($id_hist_plan, $dataView = array(), $cargaCompleta = FALSE)
	{
		$dataView['title'] = 'Registrar prestación';

		// Obtener prestaciones disponibles para el afiliado
		$dataView['listado_coberturas'] = $this->_getCoberturasDisponibles($id_hist_plan);
		$dataView['listado_coberturas_extras'] = $this->_getCoberturasDisponibles($id_hist_plan, TRUE);

		$dataView['idHistorialPlan'] = $id_hist_plan;

		if($cargaCompleta) $dataView['modalDesactivado'] = TRUE;

		parent::_loadViews($this->pagina_editar, $dataView, $cargaCompleta);
	}

	private function _getCoberturasDisponibles($id_hist_plan, $cobertura_extra = FALSE)
	{
		$obj_hist_plan = new Historial_plan($id_hist_plan);

		// Obtener prestaciones disponibles para el afiliado
		$this->load->library('util_historial_plan'); # Cargo la librería que necesito
		$array_prestaciones = $this->util_historial_plan->getDetallePrestaciones($obj_hist_plan);
		
		if(!$cobertura_extra) $prestaciones_pendientes = $array_prestaciones['pendientes'];
		else $prestaciones_pendientes = $array_prestaciones['pendientes_extra'];

		$listado_coberturas = $this->getArregloCoberturas($prestaciones_pendientes, $obj_hist_plan, $cobertura_extra);

		return $listado_coberturas;
	}

	private function getArregloCoberturas($prestaciones_pendientes, $obj_hist_plan, $es_extra)
	{
		$listado_coberturas = array();
		$periodo_actual = date('m') . date('Y');

		foreach ($prestaciones_pendientes as $prest_pendiente) {
			#Por cada prestación, creo una cobertura (que son las que puede registrar el prestador)
			$cobertura = new Cobertura();
			$cobertura->prestacion_id = $prest_pendiente->prestacion_id;
			$cobertura->prestacion = new Prestacion($prest_pendiente->prestacion_id);
			$cobertura->historial_plan_id = $obj_hist_plan->id;
			
			// En caso de prestaciones EXTRAS, éstas pueden entrar en vigencia al inicio del plan o en períodos posteriores.
			// Evalúo esta posibilidad antes de continuar.
			$cobertura_disponible = TRUE; # Por defecto para la mayoría de las prestaciones
			if($es_extra) { 
				$objPrestacion = new Prestacion_extra($prest_pendiente->id);
				if($objPrestacion->periodo_inicio > $periodo_actual) $cobertura_disponible = FALSE;
			}

			if($cobertura_disponible)
			{
				$estado_cobertura;
				/* La cobertura puede realizarse siempre y cuando se cumplan las restricciones de fechas (si tuviera) */
				if(!$prest_pendiente->distribucion_uniforme) #La prestación se puede consumir en cualquier momento
					$estado_cobertura = 'DISPONIBLE';
				else #Tengo que controlar que la fecha actual esté dentro de las fechas correspondientes para la realización de la prestación 
				{	
					# El listado trae las cantidades que restan, no las que originalmente se definieron, así que necesito los datos originales
					if(!$es_extra) { 
						$prest_plan_original = new Plan_prestacion($prest_pendiente->id);
						$cant_meses_plan = $prest_plan_original->plan->get()->cant_meses_duracion;
					}
					else {
						$prest_plan_original = new Prestacion_extra($prest_pendiente->id);
						$prest_plan_original->historial_plan->get();
						$cant_meses_plan = $prest_plan_original->historial_plan->plan->get()->cant_meses_duracion;
					}

					$cant_total_prestaciones = $prest_plan_original->cantidad;

					if($cant_meses_plan > 0)
					{
						#El intervalo está expresado en meses
						$intervalo_entre_prestaciones = floor($cant_meses_plan / $cant_total_prestaciones);
						$periodo_actual = $this->util_historial_plan->obtenerPeriodo(date('Y/m/d'));

						#Si desde la última cobertura realizada al afiliado (con el mismo tipo de prestación) al día actual, 
						#pasó el tiempo correspondiente (intervalo_entre_prestaciones), entonces está habilitado para realizar
						#nuevamente dicha cobertura.
						$periodo_ultima_cobertura_realizada = $this->_getPeriodoUltimaCoberturaRealizada($prest_plan_original->prestacion_id, $obj_hist_plan->id);
						if($periodo_ultima_cobertura_realizada != 0) #Se realizó previamente una cobertura de este tipo
						{
							#Obtengo en qué período debiera volver a estar habilitada la prestación
							$periodo_cobertura_habilitada = $this->util_historial_plan->getPeriodoIntervalo($periodo_ultima_cobertura_realizada, $intervalo_entre_prestaciones);
						}
						else { #No se encontró cobertura previa ya realizada
							#Si nunca se realizó este tipo de cobertura antes, ésta estará disponible si al día actual pasó el 
							#tiempo entre la fecha de inicio del plan más el intervalo_entre_prestaciones
							$periodo_cobertura_habilitada = $this->util_historial_plan->obtenerPeriodo($obj_hist_plan->fecha_inicio);				
						}

						if($periodo_cobertura_habilitada == $periodo_actual) $estado_cobertura = 'DISPONIBLE';
						else $estado_cobertura = 'NO DISPONIBLE TEMPORALMENTE';

					}
					else $estado_cobertura = 'NO DISPONIBLE';
				}
			}
			else $estado_cobertura = 'NO DISPONIBLE TEMPORALMENTE'; 

			$cobertura->estado = $estado_cobertura;
			$listado_coberturas[] = $cobertura;
		}

		return $listado_coberturas;
	}

	private function _getPeriodoUltimaCoberturaRealizada($prestacion_id, $historial_plan_id)
	{
		$ultima_cobertura = new Cobertura();
		$ultima_cobertura->where('historial_plan_id', $historial_plan_id);
		$ultima_cobertura->where('prestacion_id', $prestacion_id);
		$ultima_cobertura->limit(1);
		$ultima_cobertura->order_by('fecha_realizacion', 'desc');
		$ultima_cobertura->get();

		if($ultima_cobertura->exists()) {
			$this->load->library('util_historial_plan'); # Cargo la librería que necesito
			return $this->util_historial_plan->obtenerPeriodo($ultima_cobertura->fecha_realizacion);
		}
		else return 0;
	}

	public function guardar()
	{
		$dataView['title'] = 'Guardar Prestación';
		$dataView['error'] = '';

		// Se obtienen los datos del formulario para poblar el modelo
		$id_cobertura = is_numeric($this->input->post('txt_id')) ? $this->input->post('txt_id') : NULL;

		$obj_cobertura = new Cobertura($id_cobertura);
		$obj_cobertura->fecha_realizacion = $this->input->post('txt_fecha_realizacion');
		$obj_cobertura->estado = 'REALIZADA';
		$obj_cobertura->observaciones = $this->input->post('txt_observaciones');
		$obj_cobertura->usuario = $_SESSION[$this->template->getUsernameSessionName()];

		if($id_cobertura == 0 || $id_cobertura == NULL) $obj_cobertura->fecha_creacion = date('Y-m-d H:i:s');
		else $obj_cobertura->fecha_modificacion = date('Y-m-d H:i:s');

		$id_hist_plan = is_numeric($this->input->post('txt_hist_plan')) ? $this->input->post('txt_hist_plan') : NULL;
		$error_guardar = $this->_guardarPermitido($id_hist_plan);
		if($error_guardar == '')
		{
			$objetos_asociar = array();
			// Defino el objeto que se desea asociar
			$obj_hist_plan = new Historial_plan($id_hist_plan);
			$objetos_asociar[] = $obj_hist_plan;

			if($this->template->usuarioActualEsPrestador()) {
				$id_usuario = $_SESSION[$this->template->getIdUserSessionName()]; // Obtener el prestador logueado
				$obj_prestador = new Prestador();
				$obj_prestador->where('usuario_id', $id_usuario);
				$objetos_asociar[] = $obj_prestador->get();
			}

			$id_prestacion = is_numeric($this->input->post('rd_prestacion')) ? $this->input->post('rd_prestacion') : NULL;
			$obj_prestacion = new Prestacion($id_prestacion);
			$objetos_asociar[] = $obj_prestacion;

			// Se manejan transacciones para interactuar con la BD
			$obj_cobertura->trans_begin();
			$operacion_exitosa = $obj_cobertura->save($objetos_asociar);
			if(!$operacion_exitosa && !$obj_cobertura->valid) // Falló la validación de datos
			{
				// Vuelvo a cargar el formulario de edición y mostrar los errores de validación
				$dataView['error'] = $obj_cobertura->error->string;
				$this->registrar($id_hist_plan, $dataView, TRUE);
			}
			else
			{
				if ($obj_cobertura->trans_status() === FALSE) // Se chequea el estado de la transacción
				{
				    $obj_cobertura->trans_rollback(); // Si la transacción falló, hago un rollback
				}
				else
				{
				    $obj_cobertura->trans_commit(); // Transacción exitosa, realizo el commit
				}

				$dataView['error'] = $obj_cobertura->error->string; // Almaceno todos los errores que hubieran podido ocurrir
				$this->ver_todos($dataView);
			}
		}
		else
		{
			// Vuelvo a cargar el formulario de edición y mostrar los errores de validación
			$dataView['error'] = $error_guardar;
			$dataView['path_volver'] = 'afiliados/ver_todos';
			parent::_loadViews($this->template->getErrorMessageView(), $dataView);
		}		
	}

	private function _guardarPermitido($id_hist_plan)
	{
		$this->load->library('util_historial_plan'); # Cargo la librería que necesito
		// Debo validar que el usuario esté activo y que el plan esté vigente
		$obj_hist_plan = new Historial_plan($id_hist_plan);
		$obj_hist_plan->afiliado->get();

		if($obj_hist_plan->afiliado->de_baja) {
			return "No pueden registrarse prestaciones para el afiliado ya que se encuentra INACTIVO.";
		}
		else { // Si no está dado de baja, controlo la vigencia del plan actual
			$hist_plan_actual = $this->util_historial_plan->getIdHistorialPlanActual($obj_hist_plan->afiliado_id);
			if($hist_plan_actual != $id_hist_plan) return 'No pueden registrarse prestaciones para planes no vigentes.';
			else return '';
		}
	}

	public function ver_todos()
	{
		$dataView['title'] = 'Registro de Prestaciones';

		$id_prestador = 0;
		$obj_prestador = new Prestador();
		if($this->template->usuarioActualEsPrestador()) { 
			$id_usuario = $_SESSION[$this->template->getIdUserSessionName()];
			
			$obj_prestador->where('usuario_id', $id_usuario);
			$dataView['listado_prestadores'] = $obj_prestador->get();

			$id_prestador = $obj_prestador->id;
		} 
		else $dataView['listado_prestadores'] = $obj_prestador->get_iterated();

		$obj_prestacion = new Prestacion();
		$dataView['listado_prestaciones'] = $obj_prestacion->get_iterated();

		$dataView['listado'] = $this->_aplicarFiltros($id_prestador); // Obtengo todos los elementos

		parent::_loadViews($this->pagina_ver_todos, $dataView);
	}

	private function _aplicarFiltros($id_prestador = 0)
	{
		$existe_filtro = FALSE;

		// Listado de afiliados
		$obj_cobertura = new Cobertura();

		$num_afiliado = is_numeric($this->input->post('filtro_id_afiliado')) ? $this->input->post('filtro_id_afiliado') : 0;
		if($num_afiliado != 0) { $obj_cobertura->where_related_historial_plan('afiliado_id', $num_afiliado); $existe_filtro = TRUE; }

		if($id_prestador != 0) {
			$obj_cobertura->where('prestador_id', $id_prestador);
		}
		else {
			$prestador = is_numeric($this->input->post('filtro_prestador')) ? $this->input->post('filtro_prestador') : 0;
			if($prestador != 0) { $obj_cobertura->where('prestador_id', $prestador); $existe_filtro = TRUE; }
		}

		$prestacion = is_numeric($this->input->post('filtro_prestacion')) ? $this->input->post('filtro_prestacion') : 0;
		if($prestacion != 0) { $obj_cobertura->where('prestacion_id', $prestacion); $existe_filtro = TRUE; }

		$fecha_realizacion = trim($this->input->post('filtro_fecha_realizacion'));
		if($fecha_realizacion != '') { $obj_cobertura->where('fecha_realizacion', $this->util_fechas->prepararFecha($fecha_realizacion)); $existe_filtro = TRUE; }

		$realizacion_desde = trim($this->input->post('filtro_realizacion_desde'));
		if($realizacion_desde != '') { $obj_cobertura->where('fecha_realizacion >=', $this->util_fechas->prepararFecha($realizacion_desde)); $existe_filtro = TRUE; }

		$realizacion_hasta = trim($this->input->post('filtro_realizacion_hasta'));
		if($realizacion_hasta != '') { $obj_cobertura->where('fecha_realizacion <=', $this->util_fechas->prepararFecha($realizacion_hasta)); $existe_filtro = TRUE; }		

		// Si no se hubieran realizado filtros, se muestran los 10 primeros
		if(!$existe_filtro) {
			$obj_cobertura->limit(10);
			$obj_cobertura->order_by('fecha_realizacion', 'desc');
		}

		return $obj_cobertura->get_iterated();
	}

	public function ver($id_elemento, $id_hist_plan = 0)
	{
		$dataView['title'] = 'Ver Prestación Realizada';

		// Creo un objeto del modelo, para poblarlo con los datos que necesito mostrar
		$obj_cobertura = new Cobertura($id_elemento);
		$dataView['obj'.$this->nombre_entidad] = $obj_cobertura;

		if($id_hist_plan != 0) $dataView['id_hist_plan'] = $id_hist_plan;

		parent::_loadViews($this->pagina_ver, $dataView, FALSE);
	}

	public function informe($dataView = array())
	{
		$dataView['title'] = 'Generar informe de Prestaciones';
		
		$id_prestador = 0;
		$obj_prestador = new Prestador();
		if($this->template->usuarioActualEsPrestador()) { 
			$id_usuario = $_SESSION[$this->template->getIdUserSessionName()];
			
			$obj_prestador->where('usuario_id', $id_usuario);
			$dataView['listado_prestadores'] = $obj_prestador->get();

			$id_prestador = $obj_prestador->id;
		} 
		else $dataView['listado_prestadores'] = $obj_prestador->get_iterated();

		$obj_prestacion = new Prestacion();
		$dataView['listado_prestaciones'] = $obj_prestacion->get_iterated();

		parent::_loadViews($this->pagina_reporte, $dataView);
	}	

	public function generar_reporte()
	{	
		$dataView['title'] = 'Generar informe de Prestaciones';
		$titulo = 'Listado de Prestaciones';
		$dataView['titulo'] = $titulo;

		// Obtengo el listado de Afiliados a mostrar
		$listado = $this->_aplicarFiltros();
		if($listado->exists()) 
		{
			$this->load->library('to_excel');
			$objPHPExcel = $this->to_excel->getExcelObject($titulo);
			
			// Defino estilos de los títulos
			$objPHPExcel->getActiveSheet()->getStyle('A3:G3')->applyFromArray($this->to_excel->getHeadersStyle());

			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1', $titulo);
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('G1', date('d/m/Y h:m'));
			$objPHPExcel->getActiveSheet()->mergeCells('A1:F1'); // Título
			$objPHPExcel->getActiveSheet()->mergeCells('G1:H1'); // Fecha de obtención del reporte
			$objPHPExcel->getActiveSheet()->getStyle('A1:F1')->applyFromArray($this->to_excel->getTitleStyle());

			// Arranco de la fila 3 ya que dejo una en blanco
			$fila_inicio = 3;
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('A'.$fila_inicio, 'Fecha');
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('B'.$fila_inicio, 'Prestador');
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('C'.$fila_inicio, 'Prestación');
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('D'.$fila_inicio, 'N° afiliado');
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('E'.$fila_inicio, 'Plan');
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('F'.$fila_inicio, 'Titular');
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue('G'.$fila_inicio, 'Observaciones');

			$array_columnas = array('A', 'B', 'C', 'D', 'E', 'F', 'G');
			foreach($array_columnas as $col)
				 $objPHPExcel->getActiveSheet()->getColumnDimension($col)->setAutoSize(true);

			// Renombrar Hoja
			$objPHPExcel->getActiveSheet()->setTitle('Prestaciones');

			// Establecer la hoja activa, para que cuando se abra el documento se muestre primero.
			$objPHPExcel->setActiveSheetIndex(0);

			$fila = $fila_inicio;
			foreach ($listado as $prest) {
				$fila++;

				$prest->historial_plan->get();
				$prest->historial_plan->plan->get();
				$prest->historial_plan->afiliado->get();
				$prest->historial_plan->afiliado->duenio->get();
				$prest->prestador->get();
				$prest->prestacion->get();
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue('A'.$fila, $prest->fecha_realizacion);
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue('B'.$fila, $prest->prestador->nombre);
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue('C'.$fila, $prest->prestacion->nombre);
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue('D'.$fila, $prest->historial_plan->afiliado_id);
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue('E'.$fila, $prest->historial_plan->plan->nombre);
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue('F'.$fila, $prest->historial_plan->afiliado->duenio->apellido . ', ' .$prest->historial_plan->afiliado->duenio->nombre);
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue('G'.$fila, $prest->observaciones);
			}

			$dataView['objWriter'] = $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
			$dataView['objPHPExcel'] = $objPHPExcel;

			$this->load->view('reportes/report_view', $dataView);
		}
		else { 
			$dataView['error'] = 'La consulta no produjo resultados.';
			$this->informe($dataView);
		}
	}
}